<!--
Copyright 2003 Cordys R&D B.V. 

This file is part of the Cordys SAP Connector. 

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
Project  : Cordys BAC
Description : To explore the metadat of SAP backend
author : Vijaya Gopal
-->
<html xmlns:eibus onselect="selectApplication()" onbeforeapplicationclose="finalize()">
<head>
	<style>
		label{	font-size:11; font-family:verdana; font-weight:normal;	}
		.heading	{	font-size:12; font-family:verdana; font-weight:bold;	}
	</style>
	<link rel="stylesheet" type="text/css" href="/cordys/wcp/style/behaviors.css">
	<script language = "JScript">
		var selectedItem			= null;
		var selectedApplication		= null; // The application belonging to the currently selected item
		var applicationRootItem		= null;	// The reference to the first menuitem which loaded the application
		var flag_SoapFault = false ; // This is set to true everytime a SOAP fault occurs
		var xmlDoc ;
		var soapNodeDN ;
		var metadataURL = "/cordys/bac/sap/sapexplorer.htm" ;
		var filterURL = "/cordys/bac/sap/showfromtopage.htm" ;
		var interfaceURL = "/cordys/bac/sap/interfaceviewer.htm" ;
		var publishURL = "/cordys/bac/sap/sapmethodpublisher.htm" ;
		// Only these 3 IDs are used in the metadata explorer.
		var componentsID = "SAPComponents" ;
		var RFCsID = "SAPRFCs" ;
		var IDOCsID = "SAPIDOCs" ;
		function selectApplication()
		{
			selectedItem = window.event.data.menuItem;
			selectedApplication = selectedItem.data;
			if (!applicationRootItem) applicationRootItem = selectedItem;
			xmlDoc = reqGetSOAPNodes.XMLDocument.documentElement.ownerDocument ;
			var applicationClass = selectedApplication.getAttribute("class");
			switch (window.event.data.exploreType)
			{
				case "select": selectItem(applicationClass); break;
				case "expand": expandItem(applicationClass); break;
			}
		}
		function selectItem(applicationClass)
		{
			switch(applicationClass)
			{
				case "Components" :
				case "Component" :
				case "BO" :
				case "BAPI" :
				case "MsgType" :
				case "IDOCType" :
				case "RFC" :
					showDetails(applicationClass);
					break;
				default:
					tb_properties.style.display = "none" ;
					imgBackground.style.display = "block" ;
			}
		}
		function showDetails(applicationClass)
		{
			tb_properties.style.display = "block" ;
			imgBackground.style.display = "none" ;
			while(tb_properties.rows.length > 1)
				tb_properties.deleteRow();
			sp_heading.innerText = applicationClass + " Details" ;
			var dataItem = selectedApplication.selectSingleNode("data/item");
			var elements;
			if(applicationClass == "RFC")
			{
				elements = dataItem.childNodes;
			}
			else
			{
				elements = dataItem.attributes;
			}
			var noOfElements = elements.length;
			tb_properties.height = 5*noOfElements+"%" ;
			for(var i=0; i< noOfElements; i++)
			{
				var elementName = elements[i].nodeName;
				if(elementName == "hasBO" || elementName == "isBO" ) continue;
				var newRow = tb_properties.insertRow();
				var newCell1 = newRow.insertCell();
				newCell1.align = "right";
				newCell1.width = "30%";
				newCell1.innerHTML = "<label>"+ elements[i].nodeName + "</label>" ;
				var newCell2 = newRow.insertCell();
				newCell2.width = "10%";
				newCell2.innerHTML = ":" ;
				var newCell3 = newRow.insertCell();
				newCell3.width = "50%";
				newCell3.innerHTML = "<label><b>"+ elements[i].text +"</b></label>" ;
			}
		}
		function expandItem(applicationClass)
		{
			if (selectedApplication.getAttribute("loaded") == "true") return;
			flag_SoapFault = false ;
			if (applicationClass == "SOAPNodes")
			{
				//It is the root node. Load the metadata services from the current organization
			   	var clone_reqGetSOAPNodes = reqGetSOAPNodes.XMLDocument.cloneNode(true);
				clone_reqGetSOAPNodes.selectSingleNode("SOAP:Envelope/SOAP:Body/GetSOAPNodes/dn").text = application.organization;
				bdiSAP.request = clone_reqGetSOAPNodes;
				bdiSAP.parameters.receiver = null;
				bdiSAP.clear();
				bdiSAP.reset();
				if (flag_SoapFault == false )
				{
					var entryNodes = bdiSAP.data.selectNodes("data/GetSOAPNodesResponse/tuple/old/entry");
					for ( var i = 0 ; i < entryNodes.length ; i++)
					{
						var commonName = entryNodes[i].selectSingleNode("cn/string").text;
						var distinguishedName = entryNodes[i].getAttribute("dn");
						var dnNode = xmlDoc.createElement("dn");
						dnNode.text = distinguishedName ;
						addItem("SOAPNode", "", "true", commonName, commonName, dnNode);
					}
				}
			}
			else
			{
				soapNodeDN = getSOAPNodeDN(selectedItem);
				addNodes(applicationClass);
			}
			selectedApplication.setAttribute("loaded", "true");
		}

		//This is to add metadata nodes to the menu tree.
		function addNodes(applicationClass)
		{
			switch (applicationClass)
			{
				case "SOAPNode" :
					addHeaderNodes();
					break;
				case "Components" :
				case "Component" :
					addChildren();
					break;
				case "BO" :
					addBAPIs();
					break;
				case "RFCs" :
					addRFCs();
					break;
				case "MsgTypes" :
					addMsgTypes();
					break;
				case "MsgType" :
					addIdocTypes();
			}
		}
		//This is to add a node item to tree.This adds attributes, and text to nodes
		function addItem(className, display, isfolder, description, id, dataChild)
		{
			var iconsPath = "/cordys/bac/sap/images/";
			var node = applicationSkeleton.XMLDocument.documentElement.cloneNode(true);
			if (className != "")node.setAttribute("class", className);
			if (display != "")node.setAttribute("display", display);
			if (isfolder != "")node.setAttribute("isfolder", isfolder);
			node.selectSingleNode("description").text = description;
			node.selectSingleNode("caption").text = description;
			node.selectSingleNode("id").text = id;//so that it doesn't mix up with an already existing page.
			switch (className )
			{
				case "Components" :
					node.selectSingleNode("icon").text = iconsPath+"components.gif";
					break ;
				case "Component" :
					node.selectSingleNode("icon").text = iconsPath+"component.gif";
					break ;
				case "BO" :
					node.selectSingleNode("icon").text = iconsPath+"business-object.gif";
					break ;
				case "BAPI" :
					node.selectSingleNode("icon").text = iconsPath+"BAPI.gif";
					break ;
				case "RFCs" :
					node.selectSingleNode("icon").text = iconsPath+"RFCs.gif";
					break ;
				case "RFC" :
					node.selectSingleNode("icon").text = iconsPath+"RFC.gif";
					break ;
				case "MsgTypes" :
					node.selectSingleNode("icon").text = iconsPath+"Idocmessagetypes.gif";
					break ;
				case "MsgType" :
					node.selectSingleNode("icon").text = iconsPath+"Idocmessage.gif";
					break ;
				case "IDOCType" :
					node.selectSingleNode("icon").text = iconsPath+"Idoc.gif";
					break ;
			}
			if(dataChild)	node.selectSingleNode("data").appendChild(dataChild);
			if(id == "SAP_filterApplication" ) // this is the id only for the filter page
			{
				node.selectSingleNode("frame").text = "_modal" ;
				node.selectSingleNode("frame").setAttribute("features" , "dialogWidth:290px;dialogHeight:165px;center:yes;status:no;resizable:no;toolbar:no;menubar:no;location:no;titlebar:no;help:no" );
				node.selectSingleNode("url").text = filterURL;
				return node ;
			}
			if(id == "SAP_MethodPublisher") // this is the id only for the publish page
			{
				node.selectSingleNode("frame").text = "main" ;
				node.selectSingleNode("url").text = publishURL;
				return node ;
			}
			else if(id == "interfaceViewer")
			{
				node.selectSingleNode("url").text = interfaceURL;
				return node;
			}
			else
			{
				node.selectSingleNode("url").text = metadataURL;
				return selectedItem.addItem(node);
			}
		}
		// To set the flag true everytime a Soap Fault occurs
		function setSoapFaultFlag()
		{
			flag_SoapFault = true ;
		}
		//Function called when application is closed
		function finalize()
		{
			if (! applicationRootItem || ! system.containers["Menu"]) return;
			//Get the item name and id
			var appName = applicationRootItem.data.selectSingleNode("description").text;
			var appID = applicationRootItem.data.selectSingleNode("id").text;
			try
			{
				//Get all item names with this applicationRootItem
				var allItems = system.containers["Menu"].applicationWindow.menutree.getItems(appName);
				for (var i = 0; i < allItems.length; i++)
				{
					if (allItems[i].data.selectSingleNode("id").text != appID) continue;
					//Try collapsing the tree one by one
					allItems[i].getChildContainer().innerHTML = "";
					allItems[i].data.setAttribute("loaded", "false");
					allItems[i].collapse();
				}
				if (selectedItem) selectedItem.setAttribute("loaded","false");
			}
			catch(e) {}
		}
		//Shows the filter page
		function showFilterPage()
		{
			var treeItem = event.activeElement.getTreeItem();
			selectedItem = treeItem ;// To add the nodes to the tree item on which filter is clicked
			var returnData = new Object();
			var filterApplication = addItem("", "", "", "Metadata Filter", "SAP_filterApplication", null);
			returnData.from = treeItem.from ;
			returnData.to = treeItem.to ;
			var nodeNameToBeFiltered = treeItem.getLabel().innerText ;
			returnData.base = nodeNameToBeFiltered ;
			//Open modal window
			application.select(filterApplication, returnData);
			if (returnData.from || returnData.to )
			{
				var fromValue = returnData.from;
				if (fromValue == "" || typeof(fromValue) == "undefined" || !fromValue.match(/\S/)) fromValue = "";
				var toValue = returnData.to;
				if (toValue == "" || typeof(toValue) == "undefined" || !toValue.match(/\S/)) toValue = "";
				treeItem.from = fromValue ;
				treeItem.to = toValue ;
				treeItem.getChildContainer().innerHTML = "";//To remove the existing items
				if (nodeNameToBeFiltered == "RFCs")
					addRFCs(fromValue, toValue);
				else if (nodeNameToBeFiltered == "IDOCMesTypes")
					addMsgTypes(fromValue, toValue);
				treeItem.data.setAttribute("loaded","true");
				treeItem.expand();
			}
		}
		// To add the children(components and BOs) of next level to the tree
		function addChildren()
		{
			var clone_reqGetComponents = reqGetComponents.cloneNode(true);
			var parentNode = selectedApplication.selectSingleNode("data/item") ;
			var parent, level;
			if(!parentNode)
			{
				parent = "000000" ; // No parent
				level = "01" ;
			}
			else
			{
				parent = parentNode.getAttribute("ID");
				level = parentNode.getAttribute("LEVEL");
			}
			clone_reqGetComponents.selectSingleNode("SOAP:Envelope/SOAP:Body/GetComponents/parent").text = parent ;
			clone_reqGetComponents.selectSingleNode("SOAP:Envelope/SOAP:Body/GetComponents/level").text = level ;
			bdiSAP.parameters.receiver = soapNodeDN;
			bdiSAP.request = clone_reqGetComponents;
			bdiSAP.clear();
			flag_SoapFault = false ;
			bdiSAP.reset();
			if (flag_SoapFault == false )
			{
				var components = bdiSAP.data.selectNodes("data/GetComponentsResponse/tuple/old/Components/item");
				var noOfComponents = components.length;
				var componentNode, className , name, shortText ;
				for(var i=0; i< noOfComponents ; i++)
				{
					componentNode = components[i].cloneNode(true);
					if(componentNode.getAttribute("isBO") == "X")
					{
						className = "BO" ;
						shortText = componentNode.getAttribute("EXT_NAME");
					}
					else
					{
						if (parent == "000000" )
							className = "Components" ;
						else
							className = "Component" ;
						shortText = componentNode.getAttribute("SHORT_TEXT");
					}
					name = componentNode.getAttribute("NAME") ;
					addItem(className, "", "true", name+"(" +shortText+")", componentsID, componentNode);
				}
			}
		}
		// To add BAPI in the selected BO to the tree
		function addBAPIs()
		{
			var clone_reqGetBAPIs = reqGetBAPIs.XMLDocument.cloneNode(true);
			var boNode = selectedApplication.selectSingleNode("data/item") ;
			clone_reqGetBAPIs.selectSingleNode("SOAP:Envelope/SOAP:Body/GetBAPIs/BO").text = boNode.getAttribute("NAME");
			bdiSAP.parameters.receiver = soapNodeDN;
			bdiSAP.request = clone_reqGetBAPIs;
			bdiSAP.clear();
			flag_SoapFault = false ;
			bdiSAP.reset();
			if (flag_SoapFault == false )
			{
				var bapiItems = bdiSAP.data.selectNodes("data/GetBAPIsResponse/tuple/old/BAPIs/item");
				var noOfBapis = bapiItems.length ;
				for(var i=0; i < noOfBapis ; i++)
				{
					var bapiItem = bapiItems[i].cloneNode(true);
					var methodName = bapiItem.getAttribute("METHODNAME");
					var addedItem = addItem("BAPI", "", "false" , methodName , componentsID, bapiItem);
					if (/developer/.test(getActiveRole(selectedItem)) == true)
						cmPublish.registerHTML(addedItem);
				}
			}
		}
		// To add the RFCs in the specified range to the tree
		function addRFCs(fromValue, toValue)
		{
			var clone_reqGetRFCs = reqGetRFCs.XMLDocument.cloneNode(true);
			clone_reqGetRFCs.selectSingleNode("SOAP:Envelope/SOAP:Body/GetRFCs/fromRFC").text = fromValue;
			clone_reqGetRFCs.selectSingleNode("SOAP:Envelope/SOAP:Body/GetRFCs/toRFC").text = toValue;
			bdiSAP.parameters.receiver = soapNodeDN;
			//bdiSAP.parameters.timeout = 50000;
			bdiSAP.request = clone_reqGetRFCs;
			bdiSAP.clear();
			flag_SoapFault = false ;
			bdiSAP.reset();
			if (flag_SoapFault == false )
			{
				var rfcItems = bdiSAP.data.selectNodes("data/GetRFCsResponse/tuple/old/RFCs/item");
				var noOfRfcItems = rfcItems.length;
				for(var i=0; i < noOfRfcItems; i++)
				{
					var rfcItem = rfcItems[i].cloneNode(true);
					var rfcName = rfcItem.selectSingleNode("FUNCNAME").text;
					var addedItem = addItem("RFC", "", "false", rfcName, RFCsID, rfcItem);
					if (/developer/.test(getActiveRole(selectedItem)) == true)
						cmPublish.registerHTML(addedItem);
				}
			}
			//bdiSAP.parameters.timeout = null;
		}
		// To add IDOCMessageTypes in the specified range to the tree
		function addMsgTypes(fromValue, toValue)
		{
			var clone_reqGetMsgTypes = reqGetMsgTypes.XMLDocument.cloneNode(true);
			clone_reqGetMsgTypes.selectSingleNode("SOAP:Envelope/SOAP:Body/GetIDOCMessageTypes/fromMSGTYPE").text = fromValue;
			clone_reqGetMsgTypes.selectSingleNode("SOAP:Envelope/SOAP:Body/GetIDOCMessageTypes/toMSGTYPE").text = toValue;
			bdiSAP.parameters.receiver = soapNodeDN;
			bdiSAP.request = clone_reqGetMsgTypes;
			bdiSAP.clear();
			flag_SoapFault = false ;
			bdiSAP.reset();
			if (flag_SoapFault == false )
			{
				var mesItems = bdiSAP.data.selectNodes("data/GetIDOCMessageTypesResponse/tuple/old/MessageTypes/item");
				var noOfMesItems = mesItems.length;
				for(var i=0; i<noOfMesItems; i++)
				{
					mesItem = mesItems[i].cloneNode(true);
					var mesType = mesItem.getAttribute("MESTYP");
					addItem("MsgType", "", "true", mesType, IDOCsID, mesItem);
				}
			}
		}
		// To add IDOC types for the selected IDOCMessageType
		function addIdocTypes()
		{
			var clone_reqGetIDOCTypes = reqGetIDOCTypes.XMLDocument.cloneNode(true);
			var mesTypeNode = selectedApplication.selectSingleNode("data/item");
			clone_reqGetIDOCTypes.selectSingleNode("SOAP:Envelope/SOAP:Body/GetIDOCTypesForMesType/MESTYPE").text = mesTypeNode.getAttribute("MESTYP");
			bdiSAP.parameters.receiver = soapNodeDN;
			bdiSAP.request = clone_reqGetIDOCTypes;
			bdiSAP.clear();
			flag_SoapFault = false ;
			bdiSAP.reset();
			if (flag_SoapFault == false )
			{
				var idocItems = bdiSAP.data.selectNodes("data/GetIDOCTypesForMesTypeResponse/tuple/old/IDOCTypes/item");
				var noOfIdocItems = idocItems.length;
				for(var i=0; i<noOfIdocItems; i++)
				{
					idocItem = idocItems[i];
					var idocName = idocItem.getAttribute("IDOCTYP");
					var addedItem = addItem("IDOCType", "", "false", idocName, IDOCsID, idocItem);
					if (/developer/.test(getActiveRole(selectedItem)) == true)
						cmPublish.registerHTML(addedItem);
				}
			}
		}
		// To get the active role under which the explorer is expanded
		function getActiveRole(item)
		{
			if (item.data.getAttribute("class") != "SOAPNodes") return getActiveRole(item.getParentItem());
			else return item.data.selectSingleNode("data/activeRole").text;
		}
		// To get the SOAP Node DN under which the explorer is expanded
		function getSOAPNodeDN(item)
		{
			if (item.data.getAttribute("class") != "SOAPNode") return getSOAPNodeDN(item.getParentItem());
			else return item.data.selectSingleNode("data/dn").text;
		}
		// To add the heads under which the metadata nodes will be displayed.
		function addHeaderNodes()
		{
			//To add Components root
			addChildren();
			// To add RFCs root
			var addedItem ;
			addedItem = addItem( "RFCs", "", "true", "RFCs", RFCsID, null);
			//Context menu for filtering
			cmFilter.registerHTML(addedItem);
			// To add IDOCMessageTypes root
			addedItem = addItem( "MsgTypes", "", "true", "IDOCMesTypes", IDOCsID, null);
			cmFilter.registerHTML(addedItem);
		}
		// To open the publish page based on the item chosen.
		function showPublishPage()
		{
			var publishApplication = addItem("","","","SAP Method Publisher", "SAP_MethodPublisher",null);
			var treeItem = event.activeElement.getTreeItem();
			var treeApplication = treeItem.data;
			var appClass = treeApplication.getAttribute("class");
			var publishData = new Object();
			publishData.soapNodeDN = soapNodeDN;
			publishData.methodType = appClass;
			publishData.selectedItem = treeApplication.selectSingleNode("data/item");
			if(appClass != "RFC")
			{
				var parentTreeItem = treeItem.getParentItem();
				var parentApplication = parentTreeItem.data;
				publishData.parentItem = parentApplication.selectSingleNode("data/item");
			}
			application.select(publishApplication, publishData);
		}
		// To show the interface of the selected IDOC or RFM in a separate page.
		function showInterface()
		{
			var treeItem = event.activeElement.getTreeItem();
			var treeApplication = treeItem.data;
			var applicationClass = treeApplication.getAttribute("class");
			var item = treeApplication.selectSingleNode("data/item");
			var paramObject = new Object();
			paramObject.soapNodeDN = soapNodeDN;
			paramObject.parentID = selectedApplication.selectSingleNode("id").text;
			if(applicationClass == "IDOCType")
			{
				paramObject.itemType = applicationClass ;
				paramObject.itemName = item.getAttribute("IDOCTYP");
				paramObject.extension = item.getAttribute("CIMTYP");
			}
			else if(applicationClass == "RFC")
			{
				paramObject.itemType = applicationClass ;
				paramObject.itemName = item.selectSingleNode("FUNCNAME").text;
			}
			else
			{
				paramObject.itemType = "RFC" ;
				paramObject.itemName = item.getAttribute("FUNCTION");
			}
			var interfaceApplication = addItem("", "", "", "Interface Viewer", "interfaceViewer", null);
			application.select(interfaceApplication, paramObject);

		}
	</script>
</head>
<!-- Data island for sending requets to the backend -->
<eibus:dataisland
	id="bdiSAP"
	automatic="false"
	async="false"
	onsoapfault = "setSoapFaultFlag()"/>
<!-- Template for adding metadat items to the menu tree when it is expanded -->
<xml id="applicationSkeleton">
	<Application >
		<description/>
		<caption/>
		<url/>
		<id/>
		<icon/>
		<frame/>
		<data/>
	</Application>
</xml>
<!-- Context menu for filtering -->
<eibus:contextmenu id="cmFilter" style="display:none">
	<eibus:menuitem onclick="showFilterPage()">Filter</eibus:menuitem>
</eibus:contextmenu>
<!-- Context menu for publising and viewing interface -->
<eibus:contextmenu id="cmPublish" style="display:none">
	<eibus:menuitem onclick="showInterface()">View Interface</eibus:menuitem>
	<eibus:menuitem onclick="showPublishPage()">Publish Method</eibus:menuitem>
</eibus:contextmenu>
<!-- Request to get SAP soap nodes with SAPSchema method set attached-->
<xml id="reqGetSOAPNodes">
	<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
	    <SOAP:Body>
			<GetSOAPNodes xmlns="http://schemas.cordys.com/1.0/ldap">
				<dn/>
				<namespace>http://schemas.cordys.com/1.0/SAPSchema</namespace>
			</GetSOAPNodes>
		</SOAP:Body>
	</SOAP:Envelope>
</xml>
<xml id="reqGetComponents">
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP:Body>
    <GetComponents xmlns="http://schemas.cordys.com/1.0/SAPSchema">
		<parent/>
		<level/>
		<overwrite>false</overwrite>
    </GetComponents>
  </SOAP:Body>
</SOAP:Envelope>
</xml>
<xml id="reqGetBAPIs">
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP:Body>
    <GetBAPIs xmlns="http://schemas.cordys.com/1.0/SAPSchema">
		<BO/>
		<overwrite>false</overwrite>
    </GetBAPIs>
  </SOAP:Body>
</SOAP:Envelope>
</xml>
<xml id="reqGetRFCs">
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP:Body>
    <GetRFCs xmlns="http://schemas.cordys.com/1.0/SAPSchema">
		<fromRFC/>
		<toRFC/>
		<overwrite>false</overwrite>
    </GetRFCs>
  </SOAP:Body>
</SOAP:Envelope>
</xml>
<xml id="reqGetMsgTypes">
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP:Body>
    <GetIDOCMessageTypes xmlns="http://schemas.cordys.com/1.0/SAPSchema">
		<fromMSGTYPE/>
		<toMSGTYPE/>
		<overwrite>false</overwrite>
    </GetIDOCMessageTypes>
  </SOAP:Body>
</SOAP:Envelope>
</xml>
<xml id="reqGetIDOCTypes">
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP:Body>
    <GetIDOCTypesForMesType xmlns="http://schemas.cordys.com/1.0/SAPSchema">
		<MESTYPE></MESTYPE>
		<overwrite>false</overwrite>
    </GetIDOCTypesForMesType>
  </SOAP:Body>
</SOAP:Envelope>
</xml>
<body>
	<img src="/cordys/wcp/images/metadata/sbackground.png" id="imgBackground" vspace="100" hspace="100" width="396" height="261">
	<table id="tb_properties" style="display:none" width="60%">
		<thead>
			<td colspan="3">
				<span  id="sp_heading" class="heading"></span>
			</td>
		</thead>
	</table>
</body>
</html>